package xyz.lwm.lazycat.utility;

import xyz.lwm.lazycat.utility.reflect.ReflectUtil;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;

/**
 * @author lwm
 */
public abstract class CollectionUtil {

    public static <T> boolean isEmpty(T[] array) {
        return array == null || array.length == 0 || array[0] == null;
    }

    public static <T> boolean isNotEmpty(T[] array) {
        return !isEmpty(array);
    }

    public static <T> boolean isEmpty(Iterable<T> iterable) {
        return iterable == null || !iterable.iterator().hasNext();
    }

    public static <T> boolean isNotEmpty(Iterable<T> iterable) {
        return !isEmpty(iterable);
    }

    public static <T> boolean isEmpty(Enumeration<T> enumeration) {
        return enumeration == null || !enumeration.hasMoreElements();
    }

    public static <T> boolean isNotEmpty(Enumeration<T> enumeration) {
        return !isEmpty(enumeration);
    }

    public static <C extends Collection<T>, T> C collect(Iterable<T> iterable, Supplier<C> supplier) {
        Assert.notNull(iterable, "iterable");
        Assert.notNull(supplier, "supplier");
        C ts = supplier.get();
        for (T t : iterable) {
            ts.add(t);
        }
        return ts;
    }

    public static <C extends Collection<T>, T> C collect(T[] array, Supplier<C> supplier) {
        Assert.notEmpty(array, "array");
        Assert.notNull(supplier, "supplier");
        C ts = supplier.get();
        ts.addAll(Arrays.asList(array));
        return ts;
    }

    public static <C extends Collection<T>, T> C collect(Enumeration<T> enumeration, Supplier<C> supplier) {
        Assert.notNull(enumeration, "enumeration");
        Assert.notNull(supplier, "supplier");
        C ts = supplier.get();
        while (enumeration.hasMoreElements()) {
            ts.add(enumeration.nextElement());
        }
        return ts;
    }

    @SuppressWarnings("unchecked")
    public static <C extends Collection<T>, T> C newCollection(Class<C> clz) {
        int modifiers;
        if (Collection.class.equals(clz) || List.class.equals(clz)) {
            return (C) new ArrayList<>();
        } else if (Set.class.equals(clz)) {
            return (C) new HashSet<>();
        } else if (Modifier.isPublic(modifiers = clz.getModifiers())
                && !Modifier.isAbstract(modifiers) && !Modifier.isInterface(modifiers)) {
            return ReflectUtil.newInstance(clz);
        } else {
            return null;
        }
    }

}
